/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package compiladores2;

/**
 *
 * @author Yoas
 */
public class Tabla {
        Token dato;
        int tamano;	
        Nodo l;
        int posicion;

	public Tabla() {
		this.l = new Nodo();//se crea el nodo y se apunta a si mismo
		this.l.sig=l; 
		this.l.ant=l;
		this.tamano=0;
                this.posicion=0;
	}

        /**
	 * Método que dice si la Tabla esta vacia
	 *
	 * @return true: en caso de que este vacia; false: en caso contrario
	 */
	private boolean esVacia() {
		return this.l.sig==this.l && this.l.ant==this.l;
		//es vacia si se apunta a si mismo el nodo L
	}
	
        /**
	 * Método para insertar un Token en la Tabla
	 * @param dato: es el Token a insertar en la Tabla
	 * @return true: en caso de insercion exitosa; false: en caso contrario
	 */
	boolean insertar(Token dato){
		if(this.esVacia()){//Si es vacia
			this.l.dato=dato;
			this.l.sig=null;
			this.l.ant=null;
			this.tamano++;
			return true;
		}else{//Si no es vacia
			if(this.buscar(dato) == -1 ){//Si no existe -> se inserta
				Nodo nodoNuevo= new Nodo(dato,posicion);//Se crea un nodo
				nodoNuevo.sig=this.l.sig;//el sig. del nuevo apuntara al sig. de L
				nodoNuevo.ant=this.l;//i.e. se anade el nodo enseguida del nodo L
				if(this.l.sig!=null) //i.e. cuando no se mete el segundo
					this.l.sig.ant=nodoNuevo;
				this.l.sig=nodoNuevo;//Cuando se mete el segundo
				this.l = nodoNuevo; //ahora L apunta al ultimo
                                this.l.posicion++;
                                posicion++;
				this.tamano++;
				return true;
			}
			return false;//Si ya existe -> No se inserta
		}
	}
	
        /**
	 * Método para buscar un Token en la Tabla
	 * @param x: es el Token a buscar en la Tabla
	 * @return int: posicion del Token en la Tabla; -1: en caso de que
         * no se encuentre el Token buscado en la Tabla
	 */
	int buscar(Token x){
		int i = this.tamano - 1;
		if(this.l.dato.equals(x))
			return i;
		else{
			Nodo aux=this.l.sig;
			while(aux!=null){
				i--;
				if(aux.dato.equals(x))
					return i;
				aux=aux.sig;
			}
			aux=this.l.ant;
			while(aux!=null){
				i--;
				if(aux.dato.equals(x))
					return i;
				aux=aux.ant;
			}
		}	
		return -1;
	}
	
	/**
	 * Método para obtenerr un Token en la Tabla
	 * @param x: es el Token a obtener de la Tabla
	 * @return Nodo: el nodo de la lista que contiene el Token deseado;
         * null: en caso de que no se encontrara el Token en la Tabla
	 */
	Nodo getNodo(Token x){
		if(this.l.dato.equals(x))
			return this.l;
		else{
			Nodo aux=this.l.sig;
			while(aux!=null){
				if(aux.dato.equals(x))
					return aux;
				aux=aux.sig;
			}
			aux=this.l.ant;
			while(aux!=null){
				if(aux.dato.equals(x))
					return aux;
				aux=aux.ant;
			}
		}	
		return null;
	}
	
        /**
	 * Método para borrar un Token en la Tabla
	 * @param x: es el Token a borrar en la Tabla
	 * @return true: en caso de borrado exitoso; false: en caso contrario
	 */
	boolean borrar(Token x){
		Nodo aux = getNodo(x);
		if(aux!=null){
			if(aux.ant==null && aux.sig==null){
				aux.sig=aux;
				aux.ant=aux;
			}else if(aux.ant==null){
				aux.sig.ant=aux.ant;
			}else if(aux.sig==null){
				aux.ant.sig=aux.sig;
				this.l=this.l.ant;
			}else{
				aux.ant.sig=aux.sig;
				aux.sig.ant=aux.ant;
			}
			this.tamano--;
                        this.l.posicion--;
			return true;
		}
		return false;
	}
	/**
	 * Método para modificar un Token en la Tabla
	 * @param x: es el Token a modificar en la Tabla
         * @param y: es el Token por el cual se modificara el Token x
	 * @return true: en caso de modificacion exitosa; false: en caso contrario
	 */
	boolean modificar (Token x, Token y){
		Nodo aux = getNodo(x);
		int aux2 = buscar(y);
		if(aux != null && aux2 == -1){
			aux.dato = y;
			return true;
		}
		return false;
	}
	
	/**
	 * Método para imprimir la Tabla
	 * @return una cadena que muestra el contenido de la Tabla
	 */
	@Override
	public String toString() {
		String cad="FIN[ ";
		if(!this.esVacia()){
			Nodo aux=this.l;
			while(aux!=null){
				cad+=aux.toString();
				aux=aux.ant;
			}
		}
		return cad+"]INICIO";
	}
	
	


}

